package com.twu.biblioteca;

import java.util.ArrayList;

public class BibliotecaApp {

    private final IOHandlerInterface handler;
    private ArrayList<Book> bookShelf;
    private ArrayList<Movie> movieShelf;
    private Member currentUser;
    private ArrayList<Member> membersList;

    public BibliotecaApp(IOHandlerInterface stringHandler) {
        handler = stringHandler;
        currentUser = null;
    }

    public static void main(String[] args) {
        BibliotecaApp app = new BibliotecaApp(new IOHandler(new Validator(), new ReadFromKeyboard()));
        app.start();

        while (true) {
            while (app.getCurrentUser() == null) {
                app.getHandler().printMenu(app.createNotLoggedInMenu());
                app.selectFromNotLoggedInMenu(app.askForValidOptionFromMenu(app.createNotLoggedInMenu()));
            }

            while (app.getCurrentUser() != null) {
                app.getHandler().printMenu(app.createLoggedInUserMenu());
                app.selectFromLoggedInMenu(app.askForValidOptionFromMenu(app.createLoggedInUserMenu()));
            }
        }

    }

    public ArrayList<Movie> getMovieShelf() {
        return movieShelf;
    }

    int askForValidOptionFromMenu(ArrayList<String> optionList) {
        return this.getHandler().returnValidInput(optionList.size());
    }

    Book selectAValidBookFromBooks(ArrayList<Book> optionList) {
        String message = "\nPlease select a book for reservation\n";
        this.getHandler().printlnMessage(message);
        int input = this.getHandler().returnValidInput(optionList.size());
        return bookShelf.get(input - 1);
    }

    public IOHandlerInterface getHandler() {
        return handler;
    }

    public ArrayList<Book> getBookShelf() {
        return bookShelf;
    }

    public void setBookShelf() {
        ArrayList<Book> bookShelf = new ArrayList<Book>();

        bookShelf.add(new Book("Great Expectations", "Charles Dickens", true));
        bookShelf.add(new Book("The Adventures of Sherlock Holmes", "Arthur Conan Doyle", false));
        bookShelf.add(new Book("The Tipping Point: How Little Things Can Make a Big Difference", "Malcolm Gladwell", true));

        this.bookShelf = bookShelf;
    }

    public void setMovieShelf() {
        ArrayList<Movie> movieShelf = new ArrayList<Movie>();
        movieShelf.add(new Movie("Sholay", 1975, "Ramesh Sippy", "N/A"));
        movieShelf.add(new Movie("Gone with the wind", 1939, "Victor Fleming", "8.2"));
        movieShelf.add(new Movie("Batman", 1989, "Tim Burton", "7.6"));
        movieShelf.add(new Movie("Edward Scissorhands", 1990, "Tim Burton", "8.0"));
        movieShelf.add(new Movie("District 9", 2009, "Neill Blomkamp", "8.0"));
        movieShelf.add(new Movie("Tangled", 2010, "Nathan Greno, Byron Howard", "7.8"));
        movieShelf.add(new Movie("Spirited Away", 2001, "Hayao Miyazaki", "8.6"));
        movieShelf.add(new Movie("Gladiator", 2000, "Ridley Scott", "8.5"));
        movieShelf.add(new Movie("Blood Diamond", 2006, "Edward Zwick", "8.0"));
        movieShelf.add(new Movie("Moulin Rouge!", 2001, "Baz Luhrmann", "7.6"));
        movieShelf.add(new Movie("He's Just Not That Into You", 2009, "Ken Kwapis", "6.3"));
        movieShelf.add(new Movie("The Holiday", 2006, "Nancy Meyers", "6.8"));
        movieShelf.add(new Movie("A Lot Like Love", 2005, "Nigel Cole", "6.4"));
        movieShelf.add(new Movie("Star Trek Into Darkness", 2013, "J.J. Abrams", "8.2"));
        movieShelf.add(new Movie("The Shawshank Redemption", 1994, "Frank Darabont", "9.3"));

        this.movieShelf = movieShelf;
    }

    public ArrayList<String> createNotLoggedInMenu() {
        ArrayList<String> menu = new ArrayList<String>();
        menu.add(" List Books");
        menu.add(" List Movies");
        menu.add(" Membership");
        menu.add(" Log in");
        menu.add(" Exit");
        return menu;
    }

    public ArrayList<String> createLoggedInUserMenu() {
        ArrayList<String> menu = new ArrayList<String>();
        menu.add(" List Books");
        menu.add(" Reserve Books");
        menu.add(" List Movies");
        menu.add(" Membership");
        menu.add(" Log out");
        menu.add(" Exit");
        return menu;
    }

    public void setMembersList() {
        LibraryNumberGenerator generator = new LibraryNumberGenerator();
        ArrayList<Member> memberList = new ArrayList<Member>();
        memberList.add(new Member(generator.getNextLibraryNumber(), "Alina Balusescu", "PassWord1", "Alina.Balusescu@tw.com", "07123 456 789".trim()));
        memberList.add(new Member(generator.getNextLibraryNumber(), "Mike Kay", "PassWord1", "Mike.Kay@tw.com", "07123 456 789".trim()));
        memberList.add(new Member(generator.getNextLibraryNumber(), "Taheerah Atchia", "PassWord1", "Taheerah.Atchia@tw.com", "07123 456 789".trim()));
        memberList.add(new Member(generator.getNextLibraryNumber(), "Linda Roy", "PassWord1", "Linda.Roy@tw.com", "07123 456 789".trim()));

        this.membersList = memberList;
    }


    public void printBookShelf() {
        this.printBookTableHeading();
        for (Book book : this.getBookShelf())
            this.getHandler().printBook(this.getBookShelf().indexOf(book) + 1, book);
    }

    public void printBookTableHeading() {
        getHandler().printBookHeader();
    }

    public void selectFromLoggedInMenu(int input) {
        switch (input) {
            case 1:
                this.printBookShelf();
                break;

            case 2:
                this.printBookShelf();
                Book selectedBook = selectAValidBookFromBooks(this.getBookShelf());
                reserveABook(selectedBook);
                break;

            case 3:
                this.listAllMovies();
                this.getHandler().printMovieDetails(this.selectAMovie(movieShelf));
                break;

            case 4:
                this.getHandler().printUserDetails(getCurrentUser());
                break;

            case 5:
                this.logoutUser();
                this.getHandler().printlnMessage("\nYou are now logged out.\n");
                break;

            case 6: {
                this.getHandler().printlnMessage("\nThank you for using Biblioteca\n");
                System.exit(0);
                break;
            }
        }
    }

    public void reserveABook(Book selectedBook) {
        try {
            selectedBook.reserve();
            this.getHandler().printlnMessage("Thank you! Enjoy the book.\n");

        } catch (BookUnavailableException e) {
            this.getHandler().printlnMessage(e.getErrorMessage());
        }
    }


    public void selectFromNotLoggedInMenu(int input) {
        switch (input) {
            case 1:
                this.printBookShelf();
                break;

            case 2:
                this.listAllMovies();
                break;

            case 3:
                this.getHandler().printlnMessage("\nPlease talk to a Librarian. Thank you.\n");
                break;

            case 4:
                this.setMembersList();
                String username = this.readUsername();
                String password = this.readPassword();
                loginUser(username, password);
                break;

            case 5: {
                this.getHandler().printlnMessage("\nThank you for using Biblioteca\n");
                System.exit(0);
                break;
            }
        }

    }


    public void start() {
        String welcomeMessage = "\nWelcome to Biblioteca!";
        getHandler().printlnMessage(welcomeMessage);
        setBookShelf();
    }

    public void listAllMovies() {
        setMovieShelf();
        for (Movie movie : movieShelf) {
            getHandler().printMovie(movieShelf.indexOf(movie) + 1, movie);
        }
    }

    public Movie selectAMovie(ArrayList<Movie> optionList) {
        String message = "\nPlease select a movie for more details\n";
        this.getHandler().printlnMessage(message);
        int input = this.getHandler().returnValidInput(optionList.size());
        return movieShelf.get(input - 1);
    }

    public Member getCurrentUser() {
        return currentUser;
    }

    public void setCurrentUser(Member currentUser) {
        this.currentUser = currentUser;
    }

    public ArrayList<Member> getMembersList() {
        return membersList;
    }

    public Member verifyLogin(String username, String password) throws InvalidLoginException {
        for (Member member : membersList) {
            if (member.getUsername().equals(username) && (member.getPassword().equals(password)))
                return member;
        }
        throw new InvalidLoginException();
    }

    public void loginUser(String username, String password) {
        try {
            Member loggedInMember = verifyLogin(username, password);
            setCurrentUser(loggedInMember);

        } catch (InvalidLoginException invalidLoginException) {
            this.getHandler().printlnMessage(invalidLoginException.getErrorMessage());
        }
    }

    public String readUsername() {
        this.getHandler().printMessage("Please enter your library card number:  ");
        return this.getHandler().getReader().readString();
    }

    public String readPassword() {
        this.getHandler().printMessage("Please enter your password:  ");
        return this.getHandler().getReader().readString();
    }

    public void logoutUser() {
        this.setCurrentUser(null);
    }
}
